package com.yeyks.controller;

import com.yeyks.dal.dao.CouponInfoMapper;
import com.yeyks.dal.dao.HotelInfoMapper;
import com.yeyks.dal.dao.RoomInfoMapper;
import com.yeyks.dal.dao.UserCouponInfoMapper;
import com.yeyks.dal.domain.*;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.CouponConst;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.util.Utility;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.CouponConst;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.util.Utility;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.security.InvalidParameterException;
import java.util.Date;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping(value = "/ajax/coupon")
public class CouponController {

    @Autowired
    AccountService accountService;

    @Autowired
    CouponInfoMapper couponInfoMapper;

    @Autowired
    UserCouponInfoMapper userCouponInfoMapper;

    @Autowired
    HotelInfoMapper hotelInfoMapper;

    @Autowired
    RoomInfoMapper roomInfoMapper;

    /**
     * 根据指定的条件查询符合条件的优惠券
     * @param request
     * @param response
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/getAvailable", method = RequestMethod.POST)
    public ResponseEntity<?> getAvailable(
            HttpServletRequest request, HttpServletResponse response
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();
        try {
            List<CouponInfo> couponInfos = couponInfoMapper.selectAvailable(null, null);

            responseBody.setBody(couponInfos);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 根据一定条件查询当前用户的优惠券
     * @param request
     * @param response
     * @param token
     * @param used 是否已经使用
     * @param valid 优惠券是否有效
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/userList", method = RequestMethod.POST)
    public ResponseEntity<?> userList(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "used", defaultValue = "", required = true) Boolean used,
            @RequestParam(name = "valid", defaultValue = "", required = true) Boolean valid
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();
        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.User) {
                throw new PermissionInvalidException();
            }

            List<Map> couponInfos = couponInfoMapper.selectByUser(accountInfo.getId(), used, valid, null);

            responseBody.setBody(couponInfos);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 用户通过优惠券id选择优惠券
     * @param request
     * @param response
     * @param token
     * @param ids
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/userPick", method = RequestMethod.POST)
    public ResponseEntity<?> userPick(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "ids", defaultValue = "", required = true) String ids

    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();
        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.User) {
                throw new PermissionInvalidException();
            }

            List<Integer> idList = Utility.str2intList(ids);

            for (Integer id : idList) {
                CouponInfo couponInfo = couponInfoMapper.selectByPrimaryKey(id);
                if (couponInfo.getStatus() != CouponConst.statusGetting) {
                    responseBody.setCode(ResponseStatus.RS_COUPON_INVALID_STATUS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_COUPON_INVALID_STATUS.getMsg());
                    return ResponseEntity.ok(responseBody);
                }

                UserCouponInfo arg = new UserCouponInfo();
                arg.setCouponId(id);
                int cnt = userCouponInfoMapper.countOfUserIdCouponId(arg);
                if (cnt >= couponInfo.getCount()) {
                    responseBody.setCode(ResponseStatus.RS_COUPON_MAX_COUNT.getCode());
                    responseBody.setMsg(ResponseStatus.RS_COUPON_MAX_COUNT.getMsg());
                    return ResponseEntity.ok(responseBody);
                }

                arg.setUserId(accountInfo.getId());
                cnt = userCouponInfoMapper.countOfUserIdCouponId(arg);
                if (cnt >= couponInfo.getCountPerUser()) {
                    responseBody.setCode(ResponseStatus.RS_COUPON_USER_MAX_COUNT.getCode());
                    responseBody.setMsg(ResponseStatus.RS_COUPON_USER_MAX_COUNT.getMsg());
                    return ResponseEntity.ok(responseBody);
                }

                UserCouponInfo userCouponInfo = new UserCouponInfo();
                userCouponInfo.setUserId(accountInfo.getId());
                userCouponInfo.setCouponId(id);
                userCouponInfo.setUsed(false);
                int rec = userCouponInfoMapper.insertReturnId(userCouponInfo);
                if (rec == 0) {
                    throw new Exception("inserted 0 row.");
                }
            }

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 通过指定条件分页查询优惠券
     * @param request
     * @param response
     * @param token
     * @param dateBegin
     * @param dateEnd
     * @param type
     * @param status
     * @param keyword
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ResponseEntity<?> list(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "dateBegin", defaultValue = "", required = true) String dateBegin,
            @RequestParam(name = "dateEnd", defaultValue = "", required = true) String dateEnd,
            @RequestParam(name = "type", defaultValue = "", required = true) Integer type,
            @RequestParam(name = "status", defaultValue = "", required = true) Integer status,
            @RequestParam(name = "keyword", defaultValue = "", required = true) String keyword,
            @RequestParam(name = "pageNum", defaultValue = "", required = true) Integer pageNum,
            @RequestParam(name = "pageSize", defaultValue = "", required = true) Integer pageSize
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
//            if (accountInfo.getType() > AccountType.BranchManager) {
//                throw new PermissionInvalidException();
//            }
//            if (accountInfo.getType() > AccountType.CityAgent) {
//                throw new PermissionInvalidException();
//            }
            if (accountInfo.getType() == AccountType.CityManager
                    || accountInfo.getType() == AccountType.HotelManager
                    || accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            Integer offset = null, maxrow = null;
            if (pageNum != 0 && pageSize != 0) {
                offset = (pageNum - 1) * pageSize;
                maxrow = pageSize;
            }
            List<CouponInfo> couponInfos = couponInfoMapper.selectByFilter(type, status, keyword, dateBegin, dateEnd, offset, maxrow);
            int count = couponInfoMapper.countByFilter(type, status, keyword, dateBegin, dateEnd);
            responseBody.addMapBody("list", couponInfos);
            responseBody.addMapBody("count", count);

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 通过券id以及roomId和hotelId查询已领但未使用的个数
     * @param request
     * @param response
     * @param token
     * @param couponId
     * @param roomId
     * @param hotelId
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/checkValid", method = RequestMethod.POST)
    public ResponseEntity<?> list(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "couponId", defaultValue = "", required = true) Integer couponId,
            @RequestParam(name = "roomId", defaultValue = "", required = true) Integer roomId,
            @RequestParam(name = "hotelId", defaultValue = "", required = true) Integer hotelId
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.User) {
                throw new PermissionInvalidException();
            }

            Date now = new Date();
            CouponInfo couponInfo = couponInfoMapper.selectByPrimaryKey(couponId);
            if (couponInfo == null) {
                throw new Exception("Cannot find the coupon");
            } else if (now.getTime() < couponInfo.getValidStart().getTime() &&
                    now.getTime() > couponInfo.getValidEnd().getTime()) {
                responseBody.setCode(ResponseStatus.RS_COUPON_INVALID_DATE.getCode());
                responseBody.setMsg(ResponseStatus.RS_COUPON_INVALID_DATE.getMsg());
                return ResponseEntity.ok(responseBody);
            }

            if (hotelId == null || hotelId == 0) {
                RoomInfo roomInfo = roomInfoMapper.selectByPrimaryKey(roomId);
                if (roomInfo == null || roomInfo.getHotelId() == 0) {
                    throw new Exception("Cannot find room information.");
                }

                hotelId = roomInfo.getHotelId();
            }

            if (hotelId == null || hotelId == 0) {
                throw new Exception("Hotel id is empty");
            }

            List<Map> validList = userCouponInfoMapper.selectValid(couponId, hotelId);

            responseBody.setBody(validList.size());
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }


    /**
     * 增加券
     * @param request
     * @param response
     * @param token
     * @param valStart
     * @param valEnd
     * @param couponInfo
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public ResponseEntity<?> add(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "valStart", defaultValue = "0", required = true) Long valStart,
            @RequestParam(name = "valEnd", defaultValue = "0", required = true) Long valEnd,
            CouponInfo couponInfo
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
//            if (accountInfo.getType() >= AccountType.HotelManager) {
//                throw new PermissionInvalidException();
//            }
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            if (valStart != null && valStart != 0) {
                couponInfo.setValidStart(new Date(valStart));
            }
            if (valEnd != null && valEnd != 0) {
                couponInfo.setValidEnd(new Date(valEnd));
            }
            if (couponInfo.getType() == null) {
                couponInfo.setType(CouponConst.typeReduction);
            }
            couponInfo.setStatus(CouponConst.statusInitialized);

            couponInfo.setRemainCount(couponInfo.getCount());
            couponInfo.setGetCount(0);
            int rec = couponInfoMapper.insertReturnId(couponInfo);
            if (rec == 0) {
                throw new Exception("insered 0 row.");
            }

            responseBody.setBody(couponInfo);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 通过券id查询券详情
     * @param request
     * @param response
     * @param id
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/getInfo", method = RequestMethod.POST)
    public ResponseEntity<?> getInfo(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "id", defaultValue = "0", required = true) Integer id
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            CouponInfo couponInfo = couponInfoMapper.selectByPrimaryKey(id);

            responseBody.setBody(couponInfo);
            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 设置券结束
     * @param request
     * @param response
     * @param token
     * @param id
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/over", method = RequestMethod.POST)
    public ResponseEntity<?> over(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "id", defaultValue = "0", required = true) Integer id
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
//            if (accountInfo.getType() > AccountType.BranchManager) {
//                throw new PermissionInvalidException();
//            }
//            if (accountInfo.getType() > AccountType.CityAgent) {
//                throw new PermissionInvalidException();
//            }
            if (accountInfo.getType() == AccountType.CityManager
                    || accountInfo.getType() == AccountType.HotelManager
                    || accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            int rec = couponInfoMapper.updateValidEndNow(id);
            if (rec == 0) {
                throw new Exception("updated 0 row.");
            }

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 通过券id删除券
     * @param request
     * @param response
     * @param token
     * @param id
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/del", method = RequestMethod.POST)
    public ResponseEntity<?> del(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "id", defaultValue = "0", required = true) Integer id
    ) {
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
//            if (accountInfo.getType() > AccountType.BranchManager) {
//                throw new PermissionInvalidException();
//            }
//            if (accountInfo.getType() > AccountType.CityAgent) {
//                throw new PermissionInvalidException();
//            }
            if (accountInfo.getType() == AccountType.CityManager
                    || accountInfo.getType() == AccountType.HotelManager
                    || accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            userCouponInfoMapper.deleteByCouponId(id);

            int rec = couponInfoMapper.deleteByPrimaryKey(id);
            if (rec == 0) {
                throw new Exception("updated 0 row.");
            }

            responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
            responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            responseBody.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(responseBody);
    }
}
